< previous page page_367 next page >

Page 367
Private Sub cmdStruct2_Click()
   Dim s As Struct2
   Dim b(40) As Byte
   s.a = &H1234
   s.b = &H56789ABC
   s.c = "ABCD"
   s.d = "ABCD"
   Debug.Print "Structure contains on API call: "
   ' Alignment screws up byte count on Len command
   RtlMoveMemory b(0), s, Len(s) + 2
   ShowMemory VarPtr(b(0)), Len(s) + 2
   ' Why can't we look at the string data?
   ' Answer - temporary buffers!
   Debug.Print "In VB it contains: "
   ShowMemory VarPtr(s), LenB(s)
End Sub
The first ShowMemory call shows the contents of the structure that is passed as a DLL parameter:
Structure contains on API call:
187D98: 34 12 0 0 BC 9A 78 56 41 42 43 44 C 5B 16 0
Curiously enough, the first field 'a' has two null bytes between it and the 'b' field. The rest of the data is just as before. Where do these two extra bytes come from?
Let's take a look at the contents of the structure as stored in Visual Basic:
12F5E4: 34 12 0 0 BC 9A 78 56 41 0 42 0 43 0 44 0 F4 2E 18 0
The string is in Unicode as before, and the two extra bytes are still there.
The extra bytes exist because the individual fields within structures are stored within Visual Basic according to certain alignment rules. These rules require that every field begin on its natural boundary. In other words, the address of the first byte in the field must start at an address that is divisible by the length of the field. This means that single-byte fields can begin anywhere, 16-bit numeric fields must begin at an even address (2-byte boundary), and 32-bit long variables or pointers must begin at an address that is a multiple of 4 (4-byte boundary).
Visual Basic uses natural alignment internally and during DLL function calls. This leads to a problem in some cases, because most API functions use single-byte alignment, where all of the fields are packed against each other. This is illustrated in Figure T7-2, which shows how the struct2 structure is stored three different ways.

 
< previous page page_367 next page >